<HEAD>
  <SCRIPT SRC="../ganja.js"></SCRIPT>
</HEAD>
<BODY><SCRIPT>
// Create a Clifford Algebra with 2,0,1 metric.
Algebra(2,0,1,()=>{

  // The geometric elements of 2D PGA (from ex. 1)
  var point = (x,y)=>!(1e0 + x*1e1 + y*1e2),
      line  = (a,b,c)=>a*1e1 + b*1e2 + c*1e0;
  
  // Universal distance and angle formulas. (from ex. 2)   
  var dist  = (x,y)=>(x & y).Length,
      angle = (x,y)=>Math.acos(x | y);
      
  // Universal projection formulas. (from ex. 3)    
  var project = (a,b)=>(a | b)/b,
      reject  = (a,b)=>(a | b);
      
  // Transformations in PGA are represented by versors,
  // elements of the even subalgebra, in general compositions
  // of reflections. (the geometric product is composition.)
  
  // Both rotations and translations can be generated by exponentiating
  // the element they leave invariant. (the point you rotate around)
  var motor = (point,angle_or_distance)=>Math.E**(angle_or_distance/2 * point);
  
  // We can easily find transformations between elements of the same type
  // as the square root of their geometric product. The product of two
  // points or two parallel lines produces a translation. The product of
  // two intersecting lines produces a rotation.
  var sqrt = motor => (Math.sign(motor.s) + motor).Normalized;

  // motors can be interpolated (similar to quaternions in two ways).
  var lerp = (motor, x) => (Math.sign(motor().s)*(1-x) + x*motor).Normalized;

  // Create some points and lines to illustrate.
  var x = point(0,1),
      y = point(1.2,0.8),
      a = line(0.5,1,1.5).Normalized,
      b = line(1.4,0.8,2.5).Normalized;

  // Motors X to Y and A to B
  var xTOy = ()=>sqrt(y * x),
      aTOb = ()=>sqrt(b * a);
      
  // Create some motors. (animated with time)
  var time = ()=> performance.now()/1000,
      Z = ()=>motor(x, time()),                            // orbit around X
      U = ()=>lerp(xTOy, Math.sin(time()) * 0.5 + 0.5),    // move X to Y
      V = ()=>lerp(aTOb, Math.sin(time()) * 0.5 + 0.5),    // rotate A to B
      W = ()=>Z * U;                                       // Z after U                                       
      
  // Graph it
  document.body.appendChild(this.graph(()=>[
    "Rotations and Translations","Drag the points.",
    0x00AA88,W >>> x,"W(x)",                    // W applied to X
    0x224488,Z >>> y,"Z(y)",[x,Z >>> y],        // Z applied to y
    0x882288,U >>> x,"U(x)",V >>> a,"V(a)",     // U,V applied to x,a
    0x008844,x,"x",y,"y",                       // our two points.   
    0x008844,a,"a",b,"b",                       // our two lines.
  ],{grid:true, lineWidth:3, labels:true, animate:true}));

});
</SCRIPT></BODY>